import * as fs from "fs";
import * as path from "path";
import * as vscode from 'vscode';
import { executor } from "./executor";
import UiPanel from "./views/uiPanel";

export class cangjie {
    static sdkVersion: string = '';
    public static async createProject() {
        const projectName = await vscode.window.showInputBox({
            prompt: "Enter project name",
            placeHolder: "Cangjie Project",
        });
        let projectPath = await vscode.window.withProgress<string>(
            { location: vscode.ProgressLocation.Notification, cancellable: false },
            async (progress) => {
                progress.report({ message: `Creating a new project: ${projectName}` });
                try {
                    if (!projectName) {
                        return '';
                    }
                    const folders = await vscode.window.showOpenDialog({
                        openLabel: "Select",
                        canSelectFolders: true,
                        canSelectFiles: false,
                    });
                    const folder = folders ? folders[0].fsPath : undefined;
                    if (!folder) {
                        return '';
                    }
                    const projectPath = path.join(folder, projectName);
                    let uri = vscode.Uri.parse(projectPath);
                    await vscode.workspace.fs.createDirectory(uri);
                    return this.initCjpm(projectPath);
                } catch (error) {
                    return "";
                }
            }
        );
        if (projectPath.trim() === "") {
            vscode.window.showErrorMessage(
                "Failed to create project. Make sure you have Cangjie Sdk installed. [Learn More](https://developer.huawei.com/consumer/cn/doc/openharmony-cangjie/cj-wp-abstract)"
            );
            return;
        }
        const result = await vscode.window.showInformationMessage(
            `Project ${projectName} created at ${projectPath}`,
            "Open",
            "Cancel"
        );
        if (result === "Open") {
            vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(projectPath), false);
        }
    }

    public static async initProject(fileUri: vscode.Uri) {
        if (fileUri && fileUri.fsPath) {
            let _path = fileUri.fsPath;
            let targetPath = path.extname(_path).length > 0 ? path.dirname(_path) : _path;
            vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(targetPath), false);
            await this.initCjpm(targetPath);
        }
    }

    public static async dependenciesTools(extensionPath: string, fileUri: vscode.Uri) {
        if (fileUri && fileUri.fsPath) {
            UiPanel.createOrShow(extensionPath, fileUri);
        }
    }

    public static updateDependencies() {
        executor.runInTerminal("cjpm update");
    }

    public static buildProject() {
        executor.runInTerminal("cjpm build");
    }

    public static cleanProject() {
        executor.runInTerminal("cjpm clean");
    }

    public static async buildFile(fileUri: vscode.Uri) {
        if (fileUri && fileUri.fsPath) {
            executor.runInTerminal(`cjc "${fileUri.fsPath}"`);
        }
    }

    static initCjpm(projectPath: string): Promise<string> {
        return new Promise(async (resolve, reject) => {
            try {
                let config = vscode.workspace.getConfiguration("cangjieTools");
                let sdkPath = config.inspect<string>('sdkPath')?.globalValue ?? '',
                    file = (process.platform === 'linux' || process.platform === 'darwin') ? path.join(sdkPath, 'envsetup.sh') : path.join(sdkPath, 'envsetup.bat');
                if (!sdkPath) {
                    let count = 0;
                    sdkPath = await this.setSdkPath(config, count);
                    if (sdkPath?.toString().trim() !== '') {

                        let initCmd = (process.platform === 'linux' || process.platform === 'darwin') ? `source "${file}"` : `${file}`;
                        executor.runInTerminal(initCmd);
                        executor.runInTerminal(`cd "${projectPath}"`);
                        executor.runInTerminal('cjpm init');
                        resolve(projectPath);
                    }
                } else {
                    let initCmd = (process.platform === 'linux' || process.platform === 'darwin') ? `source "${file}"` : `${file}`;
                    executor.runInTerminal(initCmd);
                    executor.runInTerminal(`cd "${projectPath}"`);
                    executor.runInTerminal('cjpm init');
                    resolve(projectPath);
                }
                this.getSdkVer(sdkPath);
            } catch (e) {
                vscode.window.showErrorMessage(`${e}`);
            }
            reject('Failed to init project. Make sure you have Cangjie Sdk installed and Configuration the Settings.');
        });
    }

    static async setSdkPath(config: vscode.WorkspaceConfiguration, count: number): Promise<string> {
        let result = '';
        let sdkPath = await vscode.window.showOpenDialog({
            openLabel: "Select",
            canSelectFolders: true,
            canSelectFiles: false
        });
        try {
            let file = (process.platform === 'linux' || process.platform === 'darwin') ? path.join(sdkPath?.[0]?.path ?? '', 'envsetup.sh') : path.join(sdkPath?.[0]?.path ?? '', 'envsetup.bat');
            fs.accessSync(file);
            await config.update('sdkPath', sdkPath, vscode.ConfigurationTarget.Global);
            result = sdkPath?.[0].path ?? '';
        } catch (e) {
            if (count > 2) {
                vscode.window.showErrorMessage(`Retry too many times! Please set the sdk path after Comfirm the location ${e}`);
            } else {
                count++;
                vscode.window.showErrorMessage(`Wrong Sdk Path or no access! ${e}`);
                result = await this.setSdkPath(config, count);
            }
        }
        return result;
    }

    static async getSdkVer(sdkPath: string) {
        let result = await executor.exec(`${path.join(sdkPath, 'bin', 'cjc')} -v`);
        const regex = /(\d+\.\d+\.\d+)/;
        const match = regex.exec(result);
        this.sdkVersion = match?.[0].toString() ?? '';
        if (this.sdkVersion) {
            vscode.window.showInformationMessage(`Found the Cangjie Sdk! It's Version ${this.sdkVersion}! `);
        }
    }

    static showAbout(extensionPath: string) {
        let panel = vscode.window.createWebviewPanel('cj.about', 'About Cangjie Tools', vscode.ViewColumn.One, {
            enableScripts: true,
            localResourceRoots: [vscode.Uri.file(path.join(extensionPath, "app"))],
            retainContextWhenHidden: true,
        });
        const appDistPath = path.join(extensionPath, 'views'),
            appDistPathUri = vscode.Uri.file(appDistPath),
            indexPath = path.join(appDistPath, 'about.html');
        const baseUri = panel.webview.asWebviewUri(appDistPathUri);
        panel.webview.html = fs.readFileSync(indexPath, { encoding: 'utf8' }).replace('<base href="/">', `<base href="${String(baseUri)}/">`);
        panel.onDidDispose(() => panel.dispose(), null);

    }
}